package util;

import java.io.IOException;
import java.math.BigInteger;

import message.FileIO;

/**
 * 
 * @author Ralf
 *
 */
public class Domain {

	private Curve c;
	private BigInteger q;
	private BigInteger h;
	private Point g;

	/**
	 * Constructor with valid BigInteger parameters.
	 * Use parameters provided by <a href="http://tools.ietf.org/html/rfc5639">IETF</a>
	 * @param p prime number to limit the number range
	 * @param a parameter of the used curve
	 * @param b parameter of the used curve
	 * @param x x-value of the generator point
	 * @param y y-value of the generator point
	 * @param q the number of valid points in this domain
	 * @param h err... some number
	 */
	public Domain(BigInteger p, BigInteger a, BigInteger b, BigInteger x, BigInteger y, BigInteger q, BigInteger h) {
		this(new Point(x, y), new Curve(a, b, p), q, h);
	}
	
	/**
	 * Constructor using Strings.
	 * @see Domain(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger)
	 */
	public Domain(String p, String a, String b, String x, String y, String q, String h) {
		this(new BigInteger(p), new BigInteger(a), new BigInteger(b), new BigInteger(x), new BigInteger(y), new BigInteger(q), new BigInteger(h));		
	}
	
	/**
	 * Constructor using complex types and BigIntegers.
	 * @see Domain(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger)
	 */
	public Domain(Point g, Curve c, BigInteger q, BigInteger h) {
		this.g = g;
		this.c = c;
		this.q = q;
		this.h = h;
	}
	
	/**
	 * Constructor using complex types and Strings.
	 * @see Domain(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger)
	 */
	public Domain(Point g, Curve c, String q, String h) {
		this(g, c, new BigInteger(q), new BigInteger(h));
	}
	
	/**
	 * Constructor who gets its parameters from a file.
	 * The file content should be formatted like
	 * x=value
	 * y=value
	 * a=value
	 * b=value
	 * p=value
	 * q=value
	 * h=value
	 * @param filename
	 * @throws IOException 
	 */
	public Domain(String filename) {
		BigInteger x = BigInteger.ZERO;
		BigInteger y = BigInteger.ZERO;
		BigInteger a = BigInteger.ZERO;
		BigInteger b = BigInteger.ZERO;
		BigInteger p = BigInteger.ZERO;
		BigInteger q = BigInteger.ZERO;
		BigInteger h = BigInteger.ZERO;
		String fileText = new String();
		try {
			fileText = FileIO.readMessageFromFile(filename).replaceAll(
					"[ \\t]", "");
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		String[] parameters = fileText.split("[=|\\n]");
		for (int i = 0; i < parameters.length; i += 2) {

			char c = parameters[i].toLowerCase().charAt(0);
			switch (c) {
			case 'x':
				x = new BigInteger(parameters[i + 1], 16);
				break;
			case 'y':
				y = new BigInteger(parameters[i + 1], 16);
				break;
			case 'a':
				a = new BigInteger(parameters[i + 1], 16);
				break;
			case 'b':
				b = new BigInteger(parameters[i + 1], 16);
				break;
			case 'p':
				p = new BigInteger(parameters[i + 1], 16);
				break;
			case 'q':
				q = new BigInteger(parameters[i + 1], 16);
				break;
			case 'h':
				h = new BigInteger(parameters[i + 1], 16);
				break;
			}
		}
		
		if (x.equals(BigInteger.ZERO) || y.equals(BigInteger.ZERO)
				|| a.equals(BigInteger.ZERO) || b.equals(BigInteger.ZERO)
				|| p.equals(BigInteger.ZERO) || q.equals(BigInteger.ZERO)
				|| h.equals(BigInteger.ZERO)) {
			return;
		}

		this.g = new Point(x, y);
		this.c = new Curve(a, b, p);
		this.q = q;
		this.h = h;
			
	}

	
	/**
	 * @return the g
	 */
	public Point getBasePoint() {
		return g;
	}

	/**
	 * @return the c
	 */
	public Curve getCurve() {
		return c;
	}

	/**
	 * @return the q
	 */
	public BigInteger getPrimeOrder() {
		return q;
	}

	/**
	 * @return the h
	 */
	public BigInteger getCofactor() {
		return h;
	}
}
